#include<iostream>
#include<string>
#include<cstdlib>			//used for random
#include <ctime>			//used for time from random
#include <vector>
#include <cmath>
#include"Game.h"
#include"ConstantType.h"
using namespace std;

//0=SOLDIER, 1=MONOPOLY, 2=ROADBUILDING, 3=YEAROFPLENTY, 4=MARKET, 5=LIBRARY, 6=UNIVERSITY, 7=GOVERNORSHOUSE, 8=CHAPEL
Game::Game():DevTray(14,2,2,2,1,1,1,1,1){
	srand((int)time(0));	//set the seed for random generation;
	numberOfPlayers = 0;
// (WOOD, SHEEP, WHEAT, BRICK, ORE)
	ResourceSet Wood(1,0,0,0,0);
	resourceWood = Wood;
	ResourceSet Sheep(0,1,0,0,0);
	resourceSheep = Sheep;
	ResourceSet Wheat(0,0,1,0,0);
	resourceWheat = Wheat;
	ResourceSet Brick(0,0,0,1,0);
	resourceBrick = Brick;
	ResourceSet Ore(0,0,0,0,1);
	resourceOre = Ore;
	ResourceSet rCost(1,0,0,1,0);
	roadCost = rCost;
	ResourceSet sCost(1,1,1,1,0);
	settlementCost = sCost;
	ResourceSet cCost(0,0,2,0,3);
	cityCost = cCost;
	ResourceSet dCost(0,1,1,0,1);
	developmentCost = dCost;
	shuffleDev();
}

int Game::rollDice(){
	return (rand()%6+1) + (rand()%6+1);
}

void Game::choosePlayers(){

	cout << "\t\t\t Welcome to the settlers of Catan\n\n";
	//Ask for the number of players
	while (numberOfPlayers < MINPLAYERS || numberOfPlayers > MAXPLAYERS){		//force 2 to 4;
		cout << "Please enter the number of players (2 to 4): ";
		cin >> numberOfPlayers;	
		if (numberOfPlayers < MINPLAYERS || numberOfPlayers > MAXPLAYERS)
			cout << "The accepted number of players are either 2, 3 or 4.\n\n";
	}
	int i;
	//for each player retrieve its name and color
	for (i=1; i<=numberOfPlayers; i++){
		cout << endl;
		cout << "Please enter player " << i << "'s name: " ;
		cin >> playerName;
		cout << "Please choose player " << i << "'s color: " ;
		cin >> stringPlayerColor;

		if(stringPlayerColor=="RED")
			playerColor = RED;
		else if(stringPlayerColor=="GREEN")
			playerColor = GREEN;
		else if(stringPlayerColor=="BLUE")
			playerColor = BLUE;
		else if(stringPlayerColor=="YELLOW")
			playerColor = YELLOW;
		else 
			playerColor = RED;
		// add this player to the player vector
		playerVector.push_back(Player(playerName, playerColor));				//add player to list of players
	}
	// for each player set the initial available and on table developments
	for(i=0;i<numberOfPlayers; i++){
		for(int j=0; j<9;j++){
			playerVector[i].setDevelopments(i,0);			// no development cards in hand
			playerVector[i].setOnTableDevelopments(i,0);	// no development cards on table
		}
	}

	cout << endl;
	cout << "Print all our players information\n\n";
	for (i=0; i<numberOfPlayers; i++){
		playerVector[i].printPlayer();
		cout << endl;
		cout<< endl;
	}
}

bool Game::isGameEnded(vector<Player> playerVector){
	bool continueRoundRobin = true;
	bool gameEnds = false;
	int index;	// the current player from the vector of players
	while(continueRoundRobin){
		for (index=0; index<static_cast<int>(playerVector.size()); index++){
			// the first player in the round robin order who have the MAXGAMEPOINTS will stop the round robin and this player is declared the winner
			if (playerVector[index].getVictoryPoints() >= MAXGAMEPOINTS){ 
				gameEnds = true;
				continueRoundRobin = false;
			}
		}
		continueRoundRobin = false;
	}
	return gameEnds;
}

ResourceSet Game::getHexResource(int rolled){
	ResourceSet extractedSet;
	switch(rolled){
		case 2:
			extractedSet = resourceWood;
			break;
		case 3:
			extractedSet = resourceOre;
			extractedSet = extractedSet+resourceWood;
			break;
		case 4:
			extractedSet = resourceSheep;
			extractedSet = extractedSet+resourceWheat;
			break;
		case 5:
			extractedSet = resourceWheat;
			extractedSet = extractedSet+resourceSheep;
			break;
		case 6:
			extractedSet = resourceOre;
			extractedSet = extractedSet+resourceBrick;
			break;
		case 8:
			extractedSet = resourceBrick;
			extractedSet = extractedSet+resourceWheat;
			break;
		case 9:
			extractedSet = resourceWood;
			extractedSet = extractedSet+resourceSheep;
			break;
		case 10:
			extractedSet = resourceWood;
			extractedSet = extractedSet+resourceBrick;
			break;
		case 11:
			extractedSet = resourceOre;
			extractedSet = extractedSet+resourceWheat;
			break;
		case 12:
			extractedSet = resourceOre;
			break;
		default:
			break;
	}
	return extractedSet;
}

void Game::buying(string theStructure, int playerIndex){
	//cout << "player index is:"<<playerIndex<<endl;
	if(theStructure=="r"){
		playerVector[playerIndex].setResources(playerVector[playerIndex].getResources()-roadCost); // reduce his resources
		playerVector[playerIndex].setNmbOfRoads(playerVector[playerIndex].getNmbOfRoads()-1); // reduce the available roads
		playerVector[playerIndex].setVictoryPoints(playerVector[playerIndex].getVictoryPoints() + VP_ROAD);	// add victory points(for road is zero)
		// output after buying
		cout<<"\t\t### Road bought ###"<<endl;
		cout<<"After buying a road"<<endl;
		playerVector[playerIndex].printPlayer();
	}
	else if(theStructure=="s"){
		playerVector[playerIndex].setResources(playerVector[playerIndex].getResources()-settlementCost); // reduce his resources
		playerVector[playerIndex].setNmbOfSettlements(playerVector[playerIndex].getNmbOfSettlements()-1); // reduce the available settlements
		playerVector[playerIndex].setVictoryPoints(playerVector[playerIndex].getVictoryPoints() + VP_SETTLEMENT);	// add victory points(for settlement is 1)
		// output after buying
		cout<<"\t\t### Settlement bought ###"<<endl;
		cout<<"After buying a settlement"<<endl;
		playerVector[playerIndex].printPlayer();
	}
	else if(theStructure=="c"){
		playerVector[playerIndex].setResources(playerVector[playerIndex].getResources()-cityCost); // reduce his resources
		playerVector[playerIndex].setNmbOfCities(playerVector[playerIndex].getNmbOfCities()-1); // reduce the available cities
		playerVector[playerIndex].setNmbOfSettlements(playerVector[playerIndex].getNmbOfSettlements()+1); // put back a settlement to the tray
		playerVector[playerIndex].setVictoryPoints(playerVector[playerIndex].getVictoryPoints() + VP_CITY);	// we leave the vp gained from the settlement and add the vp of upgrading to city
		// output after buying
		cout<<"\t\t### City bought ###"<<endl;
		cout<<"After buying a city"<<endl;
		playerVector[playerIndex].printPlayer();
	}
	else if(theStructure=="d"){
		int drawnIndex, oldNmb;
		playerVector[playerIndex].setResources(playerVector[playerIndex].getResources()-developmentCost); // reduce his resources by the development cost
		// draw from development tray a development card
		drawnIndex = rndIndexes[rndIndexes.size()-1];
		// delete that card from the bag
		rndIndexes.pop_back();
		for(int i=0;i<static_cast<int>(rndIndexes.size());i++)
			cout<<rndIndexes[i]<<",";
		cout<<endl;

		// add in hand development cards
		oldNmb = playerVector[playerIndex].getDevelopments().getNmbOfDev(drawnIndex);
		cout<<"old number of this development:"<< oldNmb<<endl;
		oldNmb++;
		playerVector[playerIndex].setDevelopments(drawnIndex,oldNmb);
		// output after buying
		cout<<"\t\t### "<< playerVector[playerIndex].getDevelopments().getDevName(drawnIndex)<<"bought ###"<<endl;
		cout<<"After buying a development"<<endl;
		playerVector[playerIndex].printPlayer();
	}
	else
		cout<<"nothing was bought"<<endl;
}

void Game::playTurn(){
	bool gameEnded = false;
	bool buyingStructure = false;
	int rnd;
	string answer;
	string nextTurn;
	numberOfPlayers = (int)playerVector.size();
	while (!gameEnded){

		for (int i=0; i<numberOfPlayers; i++){
			rnd = rollDice();
			cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
			cout << "PLAYER " << i+1 << "'s turn: " << playerVector[i].getName() <<" rolled a: " << rnd << endl;
			cout<<"the resource generated by the random number is: "<<endl;
			getHexResource(rnd).printResourceSet();

			for(int j=0;j<numberOfPlayers;j++){
				cout<<"the player :"<<playerVector[j].getName()<<" receive this resource"<<endl;
				playerVector[j].setResources(playerVector[j].getResources() + getHexResource(rnd));
				// output after receiving the resources but before buying
			}
			cout<<"after receiving the resources but before buying"<<endl;
			playerVector[i].printPlayer();
			cout<<endl;
			cout<<"The game's tray of ";
			DevTray.printDevelopmentTray();
			cout<<endl;

			if(playerVector[i].getResources().containsAtLeast(roadCost) && playerVector[i].getNmbOfRoads()>0){
				cout<< "To buy a road press r. ";
				buyingStructure = true;
			}

			if(playerVector[i].getResources().containsAtLeast(settlementCost) && playerVector[i].getNmbOfSettlements()>0){
				cout<< "To buy a settlement press s. ";
				buyingStructure = true;
			}

			if(playerVector[i].getResources().containsAtLeast(cityCost) && playerVector[i].getNmbOfCities()>0 && playerVector[i].getNmbOfSettlements()<INITIAL_SETTLEMENTS){
				cout<< "To buy a city press c. ";
				buyingStructure = true;
			}
			
			// if player has enought resource to buy a development and there are any developments in the game's tray 
			if(playerVector[i].getResources().containsAtLeast(developmentCost) && DevTray.hasAnyDev()){
				cout<< "To buy a development card press d. ";
				buyingStructure = true;
			}

			
			if (buyingStructure){
				cin >> answer;
				buyingStructure = false;
				buying(answer,i);
			}
			else
				cin >> answer;


			gameEnded=isGameEnded(playerVector);

			if(gameEnded){
				indexOfTheWinner = i;
				break;
			}
		//	cin >> nextTurn;				//allows for another turn
		}
	}
	cout << endl;
	cout << endl;
	cout << "\t\t\t\tThe game is over"<<endl;
	cout << "\t\t\t\tThe player "<< playerVector[indexOfTheWinner].getName()<<" won"<<endl;
	cout<< "\t\t\tThanks for playing the settlers of Catan!\n";
}

void Game::shuffleDev(){
	int rnd		= 0;	// random number
	rndIndexes.reserve(25);
//0=SOLDIER, 1=MONOPOLY, 2=ROADBUILDING, 3=YEAROFPLENTY, 4=MARKET, 5=LIBRARY, 6=UNIVERSITY, 7=GOVERNORSHOUSE, 8=CHAPEL
	// Counter initialization
	int sCount	= 14;	// soldier counter
	// progress cards
	int moCount = 2;	// monopoly counter
	int rCount	= 2;	// road builiding counter
	int yCount	= 2;	// years of plenty counter
	// victory points cards
	int maCount = 1;	// market counter
	int lCount	= 1;	// library counter
	int uCount	= 1;	// university counter
	int gCount	= 1;	// governor's house counter
	int cCount	= 1;	// chapel counter

	while(rndIndexes.size()<25){
		rnd = rand()%25;
		if(rnd<14 && sCount>0){
			rndIndexes.push_back(0);
			sCount--;
		}
		if((rnd==14 || rnd==15) && moCount>0){
			rndIndexes.push_back(1);
			moCount--;
		}
		if((rnd==16 || rnd==17) && rCount>0){
			rndIndexes.push_back(2);
			rCount--;
		}
		if((rnd==18 || rnd==19) && yCount>0){
			rndIndexes.push_back(3);
			yCount--;
		}
		if(rnd==20 && maCount>0){
			rndIndexes.push_back(4);
			maCount--;
		}
		if(rnd==21 && lCount>0){
			rndIndexes.push_back(5);
			lCount--;
		}
		if(rnd==22 && uCount>0){
			rndIndexes.push_back(6);
			uCount--;
		}
		if(rnd==23 && gCount>0){
			rndIndexes.push_back(7);
			gCount--;
		}
		if(rnd==24 && cCount>0){
			rndIndexes.push_back(8);
			cCount--;
		}
	}
	for(int i=0;i<25;i++)
		cout<<rndIndexes[i]<<",";
	cout<<endl;
}